import type {Executor} from '../';
import type {ChatDTO, Flux, ImageGeneration, ServerSentEvent} from '../model/static/';

export class ChatController {

    constructor(private executor: Executor) {
    }

    /**
     * * 0 = "dashScopeAiVLChatModel"
     * * 1 = "dashScopeAiChatModel"
     * * 2 = "moonshotChatModel"
     * * 3 = "ollamaChatModel"
     *         ------qwen2.5:1.5b
     *         qwen2.5-coder:1.5b
     *
     * * 4 = "openAiChatModel"
     * * 5 = "zhiPuAiChatModel"
     *
     * @parameter {ChatControllerOptions['chat']} options
     * - chatDTO@return [String]
     */
    chat: (options: ChatControllerOptions['chat']) => Promise<
        string
    > = async (options) => {
        let _uri = '/chat/chat';
        let _separator = _uri.indexOf('?') === -1 ? '?' : '&';
        let _value: any = undefined;
        _value = options.chatDTO.modelName;
        _uri += _separator
        _uri += 'modelName='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.prompt;
        _uri += _separator
        _uri += 'prompt='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.sessionId;
        _uri += _separator
        _uri += 'sessionId='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.enableVectorStore;
        _uri += _separator
        _uri += 'enableVectorStore='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.enableFunctionCalling;
        _uri += _separator
        _uri += 'enableFunctionCalling='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.cosplay;
        _uri += _separator
        _uri += 'cosplay='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        _value = options.chatDTO.fomatJson;
        if (_value !== undefined && _value !== null) {
            _uri += _separator
            _uri += 'fomatJson='
            _uri += encodeURIComponent(_value);
            _separator = '&';
        }
        _value = options.chatDTO.jsonComment;
        if (_value !== undefined && _value !== null) {
            _uri += _separator
            _uri += 'jsonComment='
            _uri += encodeURIComponent(_value);
            _separator = '&';
        }
        const _formData = new FormData();
        const _body = options.body;
        if (_body) {
            if (_body.file) {
                for (const file of _body.file) {
                    _formData.append("file", file);
                }
            }
        }
        return (await this.executor({uri: _uri, method: 'POST', body: _formData})) as Promise<string>;
    }

    /**
     * * 0 = "dashScopeAiVLChatModel"
     * * 1 = "dashScopeAiChatModel"
     * * 2 = "moonshotChatModel"
     * * 3 = "ollamaChatModel"
     * * 4 = "openAiChatModel"
     * * 5 = "zhiPuAiChatModel"
     *
     * @parameter {ChatControllerOptions['chatStream']} options
     * - chatDTO@return [String]
     */
    chatStream: (options: ChatControllerOptions['chatStream']) => Promise<
        Flux<ServerSentEvent<string>>
    > = async (options) => {
        let _uri = '/chat/chatStream';
        const _formData = new FormData();
        const _body = options.body;
        _formData.append(
            "chatDTO",
            new Blob(
                [JSON.stringify(_body.chatDTO)],
                {type: "application/json"}
            )
        );
        if (_body.file) {
            for (const file of _body.file) {
                _formData.append("file", file);
            }
        }
        return (await this.executor({
            uri: _uri,
            method: 'POST',
            body: _formData
        })) as Promise<Flux<ServerSentEvent<string>>>;
    }

    chatTest: (options: ChatControllerOptions['chatTest']) => Promise<
        string
    > = async (options) => {
        let _uri = '/chat/chatTest';
        return (await this.executor({uri: _uri, method: 'POST', body: options.body})) as Promise<string>;
    }

    hello: (options: ChatControllerOptions['hello']) => Promise<
        string
    > = async (options) => {
        let _uri = '/chat/hello';
        let _separator = _uri.indexOf('?') === -1 ? '?' : '&';
        let _value: any = undefined;
        _value = options.string;
        _uri += _separator
        _uri += 'string='
        _uri += encodeURIComponent(_value);
        _separator = '&';
        return (await this.executor({uri: _uri, method: 'GET'})) as Promise<string>;
    }

    textToImageChat: (options: ChatControllerOptions['textToImageChat']) => Promise<
        Array<ImageGeneration>
    > = async (options) => {
        let _uri = '/chat/chat/image';
        let _separator = _uri.indexOf('?') === -1 ? '?' : '&';
        let _value: any = undefined;
        _value = options.input;
        if (_value !== undefined && _value !== null) {
            _uri += _separator
            _uri += 'input='
            _uri += encodeURIComponent(_value);
            _separator = '&';
        }
        return (await this.executor({uri: _uri, method: 'GET'})) as Promise<Array<ImageGeneration>>;
    }
}

export type ChatControllerOptions = {
    'chat': {
        chatDTO: ChatDTO,
        body?: {
            file?: Array<File> | undefined
        }
    },
    'chatStream': {
        body: {
            chatDTO: ChatDTO,
            file?: Array<File> | undefined
        }
    },
    'textToImageChat': {
        input?: string | undefined
    },
    'hello': {
        string: string
    },
    'chatTest': {
        body: ChatDTO
    }
}